import { ElMessage } from 'element-plus';
import { AxiosRequestConfig } from 'axios';
import Qs from 'qs';
import { getAxiosService } from '../util/axios';
import { Row } from './elementUI';
import type { Component } from 'vue';
import { PageName } from '../pages/pages';

/**
 * 字符串化的数值 #(true), !(false), $(number), %(string), @(json)
 *   [$, %]: ',' make array
 */
// export type Stringify = string;
// export type StringifyType = number | string | boolean;
// export type StringifyType2 = StringifyType | Record<string, unknown>;
// export type StringifyType3 = StringifyType2 | Array<StringifyType2>;
// export const stringifyCompare = (v: StringifyType, stringify: Stringify, strict = false) => {
//   const mask = stringify.charAt(0);
//
//   if (mask === '#') return strict ? v === true : !!v;
//   if (mask === '!') return strict ? v === false : !v;
//
//   const checker: Array<string | number> = stringify.substring(1).split(',');
//
//   return checker.includes(v + '');
// };
//
// export const stringifyValue: (stringify: Stringify) => StringifyType3 = (stringify) => {
//   const mask = stringify.charAt(0);
//   const value = stringify.substring(1);
//
//   if (mask === '#') return !!value;
//   if (mask === '!') return !value;
//
//   if (mask === '@') return JSON.parse(value);
//
//   let checker: Array<string | number> = value.split(',');
//   if (mask === '$') checker = checker.map((i) => Number(i));
//
//   return checker.length === 1 ? checker[0] : checker;
// };

/**
 * 关联字段名
 */
export type Sensor = string;
/**
 * 调试信息
 */
export type Trace = string;
/**
 * 图层
 */
export type Layer = 'self' | string;
/**
 * 视图
 */
export type View = {
  /**
   * 组件名称
   */
  view: PageName | string | Component;
  /**
   * 页面名称
   */
  title?: Layer;
  /**
   * 描述
   */
  description?: string;

  /**
   * 组件参数
   */
  [p: string]: unknown;
};

/**
 * 请求类型
 */
export enum RequestType {
  GET = 'get',
  POST = 'post'
}

/**
 * 指令格式
 */
export type Directive = 'redirect' | 'refresh' | string;

/**
 * 负载
 */
export type Payload = 'id' | string | '*';

/**
 * 请求参数
 */
export type Value = null | { [p: string]: unknown };

/**
 * 请求对象
 */
export interface CommandOptions {
  /**
   * 指令，视图自己处理
   */
  directive?: Directive;
  /**
   * 图层
   */
  layer?: Layer;

  /**
   * 请求路径
   */
  url?: string;
  /**
   * 请求方式 post/get
   */
  request?: RequestType;
  /**
   * 负载
   */
  payload?: Payload;

  // /**
  //  * 提交前判断
  //  */
  // before?: () => Promise<boolean | undefined> | boolean | undefined;
  // /**
  //  * 获取数据后的预处理
  //  */
  // after?: (data: unknown) => PResult;
}

/**
 * 响应结果格式
 */
export interface Result {
  /**
   * 返回值
   */
  value: unknown;
  /**
   * 错误指示
   */
  error?: boolean;
  /**
   * 调试信息列表
   */
  trace?: Array<Trace>;
  /**
   * 提示信息
   */
  message?: string;
}

export type PResult = Promise<Result | undefined>;

export interface Feedback extends CommandOptions {
  row?: Row;
}

export class Command {
  // constructor(private readonly options: CommandOptions = {}) {}

  static async Get(url: string, value: Value = null) {
    return await Command.Request(RequestType.GET, url, value);
  }

  static async Post(url: string, value: Value = null) {
    return await Command.Request(RequestType.POST, url, value);
  }

  static async Request(type: RequestType, url: string, value: Value = null) {
    // 提取Url
    if (!url) {
      ElMessage('找不到的URL参数');
      return;
    }

    // 组建option
    const option: AxiosRequestConfig = { url };

    if (type === RequestType.POST) {
      option.method = 'post';
      option.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
      if (value) option.data = Qs.stringify(value, { arrayFormat: 'brackets' });
    } else {
      option.method = 'get';
      if (value) option.params = JSON.parse(JSON.stringify(value));
    }

    // 开启跨域cookie
    option.withCredentials = true;
    // 参数处理
    option.paramsSerializer = (params) => Qs.stringify(params, { arrayFormat: 'brackets' });

    try {
      const response = await getAxiosService(option);

      const data = response?.data as Result;

      if (!data) return;

      if (data.message) ElMessage(data.message);

      return data.value;
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } catch (e: any) {
      try {
        ElMessage(e.message);
      } catch {
        console.log(e);
      }
    }
  }

  // async urlRequest(type: RequestType, url: string, value: Value) {
  //   value = setCommandPayload(this.options, value);
  //
  //   if (this.options.before && (await this.options.before()) === false) return;
  //
  //   const data = await Command.Request(type, url, value);
  //
  //   if (!data) return;
  //
  //   return this.options.after ? this.options.after(data) : data;
  // }

  // async urlGet(url: string, value: Value) {
  //   return await this.urlRequest(RequestType.GET, url, value);
  // }
  //
  // async urlPost(url: string, value: Value) {
  //   return await this.urlRequest(RequestType.POST, url, value);
  // }

  static async invoke(command: CommandOptions, value: Value = null) {
    // if (typeof command.directive === 'function') return await command.directive();
    value = setCommandPayload(command, value);
    return await Command.Request(command.request ?? RequestType.GET, command.url ?? '', value);
  }
}

function setCommandPayload(command: CommandOptions, row: Value = null): Value {
  const payload = command.payload;

  if (payload === '!') return null;

  if (payload === '*') return row;

  if (!payload) return { id: row?.id };

  const r: Value = {};
  payload.split(',').forEach((key) => (r[key] = row?.[key]));
  return r;
}
